package org.fireflow2.designer.eclipse.simulation;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ActivityInstanceState;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.ProcessInstanceState;
import org.fireflow.engine.entity.runtime.WorkItem;
import org.fireflow.engine.entity.runtime.WorkItemState;
import org.fireflow.engine.entity.runtime.impl.ProcessInstanceTrace;
import org.fireflow.pvm.kernel.Token;
//import org.fireflow2.designer.simulation.FireflowSimulator;
//import org.fireflow2.designer.simulation.persistence.IStorageChangeListener;
//import org.fireflow2.designer.simulation.persistence.MemoryPersistenceService;
//import org.fireflow2.designer.simulation.persistence.StorageChangedEvent;


public class SimulationDataView extends ViewPart{
//	implements 	IStorageChangeListener {
//	MemoryPersistenceService persistenceService = null;
	WorkitemTableViewer workitemViewer = null;
	TaskInstanceViewer taskInstanceViewer = null;
	ProcessInstanceViewer processInstanceViewer = null;
	ProcessInstanceVarViewer processInstanceVarViewer = null;
	TokenViewer tokenViewer = null;
	TraceViewer traceViewer = null;
	
	private boolean controlCreated = false;
	
	@Override
	public void createPartControl(Composite arg0) {
		// TODO Auto-generated method stub
		TabFolder tabFolder = new TabFolder(arg0, SWT.BORDER | SWT.LEFT);

		workitemViewer = new WorkitemTableViewer(tabFolder);

		TabItem tabItem = new TabItem(tabFolder, SWT.NULL);
		tabItem.setText("Work Items");
		tabItem.setControl(workitemViewer.getTable());
		
		taskInstanceViewer = new TaskInstanceViewer (tabFolder); 
		tabItem = new TabItem(tabFolder, SWT.BOTTOM);
		tabItem.setText("Task Intances");
		tabItem.setControl(taskInstanceViewer.getTable());
		
		processInstanceViewer = new ProcessInstanceViewer(tabFolder); 
		tabItem = new TabItem(tabFolder, SWT.BOTTOM);
		tabItem.setText("Process Instances");
		tabItem.setControl(processInstanceViewer.getTable());
		
		processInstanceVarViewer = new ProcessInstanceVarViewer(tabFolder);
		tabItem = new TabItem(tabFolder, SWT.BOTTOM);
		tabItem.setText("Process Instance Variables");
		tabItem.setControl(processInstanceVarViewer.getTable());
		
		tokenViewer = new TokenViewer(tabFolder);
		tabItem = new TabItem(tabFolder,SWT.BOTTOM);
		tabItem.setText("Tokens");
		tabItem.setControl(tokenViewer.getTable());
		
		traceViewer = new TraceViewer(tabFolder);
		tabItem = new TabItem(tabFolder,SWT.BOTTOM);
		tabItem.setText("Trace Info");
		tabItem.setControl(traceViewer.getTable());
		
//		persistenceService = (MemoryPersistenceService) FireflowSimulator
//				.getCurrentSimulator().getRuntimeContext()
//				.getPersistenceService();
//		persistenceService.addStorageChangeListenser(this);

		controlCreated = true;
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
		if (controlCreated)	refresh();
	}
	
	protected void refresh(){
		/*
		workitemViewer.setInput(persistenceService.getWorkItemStorage());
		taskInstanceViewer.setInput(persistenceService.getTaskInstanceStorage());
		processInstanceViewer.setInput(persistenceService.getProcessInstanceStorage());
		
		
        List vList = new ArrayList();
        List processInstanceStorage = persistenceService.getProcessInstanceStorage();
        Map processInstanceMapTmp = new HashMap();
        Object[] processInstanceArr = processInstanceStorage.toArray();
        for (int i = 0; processInstanceArr != null && i < processInstanceArr.length; i++) {
            ProcessInstance processInstance = (ProcessInstance) processInstanceArr[i];
            processInstanceMapTmp.put(processInstance.getId(), processInstance);
            Map variables = null;//processInstance.getProcessInstanceVariables();
            Iterator keyIter = variables.keySet().iterator();
            while (keyIter.hasNext()) {
                String name = (String) keyIter.next();
                Object value = variables.get(name);
                ProcessInstanceVariable4Simulation v = new ProcessInstanceVariable4Simulation(processInstance, name, value);
                vList.add(v);
            }
        }
        processInstanceVarViewer.setInput(vList);
        
        List tokens = persistenceService.getTokenStorage();
        for (int i=0;tokens!=null && i<tokens.size();i++){
        	Token token = (Token)tokens.get(i);
        	String processInstanceId = token.getProcessInstanceId();
//        	token.setProcessInstance((ProcessInstance)processInstanceMapTmp.get(processInstanceId));
        }
        tokenViewer.setInput(tokens);
        
        List traceInfos = persistenceService.findAllProcessInstanceTraces();
        for (int i=0;traceInfos!=null && i<traceInfos.size();i++){
        	ProcessInstanceTrace trace = (ProcessInstanceTrace)traceInfos.get(i);
        	ProcessInstance procInst = (ProcessInstance)processInstanceMapTmp.get(trace.getProcessInstanceId());
        	if (procInst!=null){
        		trace.setProcessInstanceId((procInst.getSubflowDisplayName()==null || procInst.getSubflowDisplayName().trim().equals(""))?procInst.getSubflowName():procInst.getSubflowDisplayName());
        	}
        }
        traceViewer.setInput(traceInfos);
        */
	}

//	public void onStorageChanged(StorageChangedEvent e) {
//		if (controlCreated)	refresh();
//	}
	
	

}

class WorkitemTableViewer extends TableViewer {
	private static final String[] columnNames = new String[] { "Id", "Name",
			"State", "Created Time", "Signed Time", "End Time", "Actor Id",
			"Comments" };
	private static final int[] columnWidths = new int[]{120,100,80,130,130,130,130,200};

	public WorkitemTableViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);
		// TODO Auto-generated constructor stub

		init();
	}

	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new WorkItemTableLabelProvider());
	}

	class WorkItemTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			WorkItem workitem = (WorkItem) element;
			switch (index) {
			case 0:
				return workitem.getId();
			case 1:
				String name = workitem.getWorkItemName();
				return name;
			case 2:
				WorkItemState state = workitem.getState();

				if (state == WorkItemState.INITIALIZED) {
					return "Initialized";
				} else if (state == WorkItemState.RUNNING) {
					return "Running";
				} else if (state == WorkItemState.COMPLETED) {
					return "Completed";
				} else if (state == WorkItemState.ABORTED) {
					return "Canceled";
				} else {
					return state.toString();
				}
			case 3:
				Date d = workitem.getCreatedTime();
				if (d == null)
					return "";
				return dFormate.format(d);
			case 4:
				d = workitem.getClaimedTime();
				if (d == null)
					return "";
				return dFormate.format(d);

			case 5:
				d = workitem.getEndTime();
				if (d == null)
					return "";
				return dFormate.format(d);
			case 6:
				String actorId = workitem.getOwnerName();
				return actorId;
			case 7:
				return workitem.getCommentSummary();
			default:
				return "";
			}
		}
	}
}

class TaskInstanceViewer extends TableViewer {
    private static final String[] columnNames = new String[]{"Id",  "Name","Step Number",
        "State",  "Create Time",
        "Start Time", "Expired Time", "End Time", "Task Type", "Assignment Strategy",
        "Task Id", "Activity Id","Process Instance Id"
    };
	private static final int[] columnWidths = new int[]{120,100,80,80,130,130,130,130,100,60,120,120,120};

	public TaskInstanceViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);
		// TODO Auto-generated constructor stub

		init();
	}

	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new TaskInstanceTableLabelProvider());
	}

	class TaskInstanceTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			ActivityInstance taskInst = (ActivityInstance) element;
			switch (index) {
			case 0:
				return taskInst.getId();
			case 1:
				String name = taskInst.getName();
				String displayName = taskInst
						.getDisplayName();
				return (displayName == null || displayName.trim().equals(""))? name : displayName;
				
			case 2:
				return taskInst.getStepNumber().toString();
			case 3:
				ActivityInstanceState state = taskInst.getState();

				if (state == ActivityInstanceState.INITIALIZED) {
					return "Initialized";
				} else if (state == ActivityInstanceState.RUNNING) {
					return "Running";
				} else if (state == ActivityInstanceState.COMPLETED) {
					return "Completed";
				} else if (state == ActivityInstanceState.ABORTED) {
					return "Canceled";
				} else {
					return state.toString();
				}
			case 4:
				Date d = taskInst.getCreatedTime();
				if (d == null)
					return "";
				return dFormate.format(d);
			case 5:
				d = taskInst.getStartedTime();
				if (d == null)
					return "";
				return dFormate.format(d);

			case 6:
				d = taskInst.getExpiredTime();
				if (d == null)
					return "";
				return dFormate.format(d);
				
			case 7:
				d = taskInst.getEndTime();
				if (d == null)
					return "";
				return dFormate.format(d);
				
			case 8:
				String taskType = taskInst.getServiceId();
				return taskType;
			case 9:
				return "AssignmentStrategy";//taskInst.getAssignmentStrategy();
			case 10:
				return taskInst.getServiceId();
			case 11:
				return taskInst.getProcessElementId();
			case 12:
				return taskInst.getProcessInstanceId();
			default:
				return "";
			}
		}
	}
}
class ProcessInstanceViewer extends TableViewer {
	private static final String[] columnNames = new String[]{"Id", "Name", "State", "Create Time",
        "Start Time", "Expired Time", "End Time", 
        "Process Id","Version","Parent Process Instance Id","Parent Task Instance Id"};
	private static final int[] columnWidths = new int[]{120,100,80,130,130,130,130,120,60,120,120};

	public ProcessInstanceViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);
		// TODO Auto-generated constructor stub

		init();
	}

	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new ProcessInstanceTableLabelProvider());
	}

	class ProcessInstanceTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			ProcessInstance processInst = (ProcessInstance) element;
			switch (index) {
			case 0:
				return processInst.getId();
			case 1:
				String name = processInst.getSubProcessName();
				String displayName = processInst
						.getSubProcessDisplayName();
				return displayName == null ? name : displayName;
			case 2:
				ProcessInstanceState state = processInst.getState();

				if (state == ProcessInstanceState.INITIALIZED) {
					return "Initialized";
				} else if (state == ProcessInstanceState.RUNNING) {
					return "Running";
				} else if (state == ProcessInstanceState.COMPLETED) {
					return "Completed";
				} else if (state == ProcessInstanceState.ABORTED) {
					return "Canceled";
				} else {
					return state.toString();
				}
			case 3:
				Date d = processInst.getCreatedTime();
				if (d == null)
					return "";
				return dFormate.format(d);
			case 4:
				d = processInst.getStartedTime();
				if (d == null)
					return "";
				return dFormate.format(d);

			case 5:
				d = processInst.getExpiredTime();
				if (d == null)
					return "";
				return dFormate.format(d);
				
			case 6:
				d = processInst.getEndTime();
				if (d == null)
					return "";
				return dFormate.format(d);
				
			case 7:
				String processId = processInst.getProcessId();
				return processId;
			case 8:
				Integer v = processInst.getVersion();
				if (v==null)return "";
				return v.toString();
			case 9:
				return processInst.getParentProcessInstanceId();
			case 10:
				return processInst.getParentActivityInstanceId();
			default:
				return "";
			}
		}
	}
}

class TokenViewer extends TableViewer{
	private static final String[] columnNames = new String[]{"Id", "Process Name","Node Id", "Step Number", "Value","Alive","From Activity Id"};
	private static final int[] columnWidths = new int[]{120,100,200,60,60,60,120};
	
	public TokenViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);

		init();
	}
	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new ProcVarTableLabelProvider());
	}

	class ProcVarTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			Token token = (Token) element;
			switch (index) {
			case 0:
				return token.getId();
			case 1:
				token.getElementId();//TODO 2.0待完善
//				if (token.getProcessInstance()!=null){
//					String dispName = token.getProcessInstance().getDisplayName();
//					String name = token.getProcessInstance().getName();
//					return (dispName==null || dispName.trim().equals(""))?name:dispName;
//				}else{
//					return "";
//				}
			case 2:
				return token.getElementId();
			case 3:
				return token.getStepNumber().toString();
			case 4:
				return token.getValue().toString();
			case 5:
				return token.isBusinessPermitted().toString();
			case 6:
				return token.getFromToken();
			default:
				return "";
			}
		}
	}
}
class TraceViewer extends TableViewer{
	private static final String[] columnNames = new String[]{"Id", "Process Name", "Step Number","Minor Number", "Type","From Node Id","To Node Id","Edge Id"};
	private static final int[] columnWidths = new int[]{120,150,60,60,100,200,200,200};
	
	public TraceViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);

		init();
	}
	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new ProcVarTableLabelProvider());
	}

	class ProcVarTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			ProcessInstanceTrace trace = (ProcessInstanceTrace) element;
			switch (index) {
			case 0:
				return trace.getId();
			case 1:
				return trace.getProcessInstanceId();
			case 2:
				return trace.getStepNumber().toString();
			case 3:
				return trace.getMinorNumber().toString();
			case 4:
				return trace.getType();
			case 5:
				return trace.getFromNodeId();
			case 6:
				return trace.getToNodeId();
			case 7:
				return trace.getEdgeId();
			default:
				return "";
			}
		}
	}
}
class ProcessInstanceVarViewer extends TableViewer {
	private static final String[] columnNames = new String[]{"Process Name", "Var Name", "Type", "Value"};
	private static final int[] columnWidths = new int[]{120,100,80,130};

	public ProcessInstanceVarViewer(Composite parent) {
		super(parent,SWT.H_SCROLL|SWT.V_SCROLL| SWT.FULL_SELECTION);
		// TODO Auto-generated constructor stub

		init();
	}

	private void init() {
		Table table = this.getTable();

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		this.setContentProvider(new ArrayContentProvider());

		this.setLabelProvider(new ProcVarTableLabelProvider());
	}

	class ProcVarTableLabelProvider extends LabelProvider implements
			ITableLabelProvider {
		SimpleDateFormat dFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		public Image getColumnImage(Object element, int index) {
			return null;
		}

		public String getColumnText(Object element, int index) {
			ProcessInstanceVariable4Simulation procVar = (ProcessInstanceVariable4Simulation) element;
			switch (index) {
			case 0:
				return procVar.getProcessDisplayName();
			case 1:
				return procVar.getName();
			case 2:
				return procVar.getType();
			case 3:
				return procVar.getValue();
			default:
				return "";
			}
		}
	}
}

class ProcessInstanceVariable4Simulation {

    String processDisplayName = null;
    String name = null;
    String type = null;
    String value = null;

    public ProcessInstanceVariable4Simulation(ProcessInstance processInstance, String name, Object value) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String procName = processInstance.getSubProcessName();
        String procDispName = processInstance.getSubProcessDisplayName();
        processDisplayName = procDispName==null?procName:procDispName;

        this.name = name;
        if (value != null) {
            if (value instanceof Integer) {
                type = "Integer";
                this.value = value.toString();
            } else if (value instanceof Float) {
                type = "Float";
                this.value = value.toString();
            } else if (value instanceof Boolean) {
                type = "Boolean";
                this.value = value.toString();
            } else if (value instanceof Date) {
                type = "Date";
                this.value = format.format((Date) value);
            } else {
                type = "String";
                this.value = value.toString();
            }
        } else {
            type = "String";
        }
    }

    public String getName() {
        return name;
    }

    public String getType() {
        return type;
    }

    public String getValue() {
        return value;
    }

    public String getProcessDisplayName() {
        return this.processDisplayName;
    }
}
